package com.um.jdy.app.charge.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingResult;
import com.um.jdy.app.charge.entity.vo.OrderItemVO;
import com.um.jdy.app.charge.entity.vo.OrderDetailVO;
import com.um.jdy.app.charge.entity.vo.OrderNumVO;
import com.um.jdy.app.charge.entity.vo.PbOrderDetailVO;
import com.um.jdy.common.commons.manager.WxManager;
import com.um.jdy.app.core.properties.HshAppProperties;
import com.um.jdy.common.base.enums.YesOrNo;
import com.um.jdy.common.charge.code.OrderCode;
import com.um.jdy.common.charge.entity.po.*;
import com.um.jdy.common.charge.entity.vo.*;
import com.um.jdy.common.charge.enums.OrderEnum;
import com.um.jdy.common.charge.service.*;
import com.um.jdy.common.commons.service.StatusService;
import com.um.jdy.common.member.enums.PayEnum;
import com.um.jdy.common.member.service.MemberUserService;
import com.um.jdy.common.sharing.entity.po.Records;
import com.um.jdy.common.sharing.service.RecordsService;
import com.um.jdy.common.system.entity.po.Param;
import com.um.jdy.common.system.service.ParamService;
import com.um.jdy.rpc.enums.DeviceTypeEnum;
import com.um.springboot.starter.entity.Page;
import com.um.springboot.starter.exception.ServiceException;
import com.um.springboot.starter.utils.StringUtil;
import com.um.springboot.starter.utils.UMBeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @Title
 * @Description
 * @Author renjunwei
 * @Date 2023/5/22 10:37
 */
@Slf4j
@Service
public class OrderManager {

    @Autowired
    MemberUserService userService;

    @Autowired
    OrderService orderService;

    @Autowired
    HshAppProperties hshAppProperties;

    @Autowired
    EbOrderService ebOrderService;

    @Autowired
    StatusService statusService;

    @Autowired
    WxManager wxManager;

    @Autowired
    RecordsService recordsService;

    @Autowired
    EvOrderService evOrderService;

    @Autowired
    EboxOrderService eboxOrderService;

    @Autowired
    PbOrderService pbOrderService;

    @Autowired
    PBOrderManager pbOrderManager;

    @Autowired
    EBOrderManager ebOrderManager;

    @Autowired
    EBoxOrderManager eboxOrderManager;

    @Autowired
    ParamService paramService;

    @Autowired
    OrderPlaceService orderPlaceService;

    @Autowired
    EVOrderManager evOrderManager;

    @Autowired
    OrderEnergyService orderEnergyService;

    /**
     * 查询订单详情
     *
     * @param id_or_no
     * @return
     */
    public OrderDetailVO getOrderInfo(String id_or_no) {
        OrderDetailVO order = orderService.getViewModel("get_order_info", OrderDetailVO.class, new String[]{id_or_no, id_or_no,userService.getComId()});
        if (null == order) {
            throw new ServiceException(OrderCode.NoOrder);
        }

        order.setOrderStatus(statusService.getOrderStatus(order.getChargeOrderId(),order.getStatus(),order.getPayStatus(),order.getDeviceType()));

        if (order.getOrderStatus() == OrderEnum.OrderStatus.Doing) {
           orderService.setOrderDurationAndAmount(order);
        }


        switch (DeviceTypeEnum.valueOf(order.getDeviceType())){
            case EB:
                EbOrder ebOrder = ebOrderService.getEntity("charge_order_id", order.getChargeOrderId());
                if(ebOrder != null) {

                    if (order.getOrderStatus() == OrderEnum.OrderStatus.Doing && StringUtil.equals(ebOrder.getFeeType(), OrderEnum.FeeType.Energy.name())) {
                        ebOrder.setServiceFee(orderService.getServiceFee(order.getChargeOrderId()));
                        ebOrder.setEnergyFee(orderService.getEnergyFee(order.getChargeOrderId()));

                        OrderEbTime orderEbTime = ebOrderManager.getCurrentEbTime(order.getChargeOrderId());
                        if (orderEbTime != null) {
                            order.setCurrentEnergyFee(orderEbTime.getPrice());
                            order.setCurrentServiceFee(orderEbTime.getServiceFee());
                        }

                        ebOrder.setChargeCapacity(orderService.getCapacity(order.getChargeOrderId()));
                        order.setChargeAmount(ebOrder.getServiceFee() + ebOrder.getEnergyFee());
                    }

                    if (order.getOrderStatus() == OrderEnum.OrderStatus.Completed  && StringUtil.equals(ebOrder.getFeeType(), OrderEnum.FeeType.Energy.name())) {
                        order.setEbEnergyList(orderService.getOrderFeeList(order.getChargeOrderId()));
                    }

                    order.setEbOrder(UMBeanUtils.copyBean(ebOrder,EbOrderVO.class));
                }

                break;
            case EV:
                EvOrder evOrder = (evOrderService.getEntity("charge_order_id",order.getChargeOrderId()));
                if(evOrder != null)
                    order.setEvOrder(UMBeanUtils.copyBean(evOrder,EvOrderVO.class));
                break;
            case EBox:
                EboxOrder eboxOrder = eboxOrderService.getEntity("charge_order_id",order.getChargeOrderId());
                if(eboxOrder != null) {
                    order.setEboxOrder(UMBeanUtils.copyBean(eboxOrder,EboxOrderVO.class));
                }
                break;
            case PB:
                PbOrderDetailVO pbOrderDetail = pbOrderService.getViewModel("get_pb_order_detail",PbOrderDetailVO.class,new Object[]{order.getChargeOrderId(),userService.getComId()});
                if(pbOrderDetail != null)
                    order.setPbOrder(pbOrderDetail);
                break;
        }

        //设置订单标说明
        if(order.getOrderStatus() == OrderEnum.OrderStatus.Doing){
            order.setExplain("正在充电中");
            if(order.getDeviceType().equals(DeviceTypeEnum.EBox.name())){
                order.setPayAmount(order.getChargeAmount());
            }
        }else if(order.getOrderStatus() == OrderEnum.OrderStatus.Completed){
            Param param = paramService.getEntity(new String[]{"path","p_key"},new Object[]{"order.explain."+order.getDeviceType(),order.getEndType()});
            if(param != null){
                order.setExplain(param.getPValue());
            }else{
                order.setExplain("您的订单已完成！");
            }
        }else if(order.getOrderStatus() == OrderEnum.OrderStatus.Place){
            order.setExplain("正在占位计费中");
            if(order.getDeviceType().equals(DeviceTypeEnum.EBox.name())){

                orderService.calcEBoxOrderPlaceFee(order,order.getEboxOrder());

            } else if (order.getDeviceType().equals(DeviceTypeEnum.EV.name())) {

                orderService.calcEVOrderPlaceFee(order,order.getEvOrder());

                // TODO 订单列表免费订单不显示订单金额，订单详情要显示，后面可能会改
                if(YesOrNo.Yes.name().equals(order.getIsFree())){
                    order.setOrderAmount(0);
                }
            }

        }else if(order.getOrderStatus() == OrderEnum.OrderStatus.UnPay){
            order.setExplain("你的订单还没有付款，请尽快支付哟");
        }

        return order;
    }

    /**
     * 分页查询充电记录
     * @param pageNo
     * @param pageSize
     * @param orderStatus
     * @return
     */
    public Page<OrderItemVO> getOrderPage(Integer pageNo, Integer pageSize, String orderStatus) {

        String userId = userService.get().getMemberUserId();
        Page<OrderItemVO> page = new Page<>();
        page.setPageNo(pageNo);
        page.setPageSize(pageSize);

        String status = "%";
        String payStatus = "%";

        //UnPay: EB->UnPayed PB->UnPayed EBox->UnPayed
        //Doing: EB->Charging  PB->Charging EBox->Charging
        //Completed: EB->Completed && Payed PB->Completed && Payed EBox->Completed && Payed

        if (orderStatus != null && !orderStatus.equals(OrderEnum.OrderStatus.All.name())) {
            if(orderStatus.equals(OrderEnum.OrderStatus.Doing.name())){
                status = OrderEnum.Status.Charging.name();
            }else if(orderStatus.equals(OrderEnum.OrderStatus.UnPay.name())){
                status = OrderEnum.Status.Completed.name();
                payStatus = PayEnum.Status.UnPayed.name();
            }else if(orderStatus.equals(OrderEnum.OrderStatus.Completed.name())){
                status = OrderEnum.Status.Completed.name();
                payStatus = PayEnum.Status.Payed.name();
            }
        }

        page = orderService.getViewModelPageBySqlName(page, "get_order_page", "get_order_count",
                OrderItemVO.class, new Object[]{payStatus,status,userId,userService.getComId()});

        page.getResult().stream().forEach(orderItem -> {
            orderItem.setOrderStatus(statusService.getOrderStatus(orderItem.getChargeOrderId(),orderItem.getStatus(),orderItem.getPayStatus(),orderItem.getDeviceType()));

            if(orderItem.getOrderStatus() == OrderEnum.OrderStatus.Doing){
                orderService.setOrderDurationAndAmount(orderItem);
            }

            if(OrderEnum.OrderStatus.Place == orderItem.getOrderStatus() && DeviceTypeEnum.EV.name().equals(orderItem.getDeviceType())){
                EvOrderVO evOrderVO = UMBeanUtils.copyBean(evOrderService.getEntity("charge_order_id",orderItem.getChargeOrderId()),EvOrderVO.class);
                orderService.calcEVOrderPlaceFee(orderItem,evOrderVO);
            }else if(OrderEnum.OrderStatus.Place == orderItem.getOrderStatus() && DeviceTypeEnum.EBox.name().equals(orderItem.getDeviceType())){
                EboxOrderVO eboxOrderVO = UMBeanUtils.copyBean(eboxOrderService.getEntity("charge_order_id",orderItem.getChargeOrderId()),EboxOrderVO.class);
                orderService.calcEBoxOrderPlaceFee(orderItem,eboxOrderVO);
            }

            if(StringUtil.equals(DeviceTypeEnum.EB.name(),orderItem.getDeviceType())){
                EbOrder ebOrder = ebOrderService.getEntity("charge_order_id", orderItem.getChargeOrderId());
                if(ebOrder != null) {
                    if (orderItem.getOrderStatus() == OrderEnum.OrderStatus.Doing && StringUtil.equals(ebOrder.getFeeType(), OrderEnum.FeeType.Energy.name())) {
                        ebOrder.setServiceFee(orderService.getServiceFee(orderItem.getChargeOrderId()));
                        ebOrder.setEnergyFee(orderService.getEnergyFee(orderItem.getChargeOrderId()));

                        orderItem.setChargeAmount(ebOrder.getServiceFee() + ebOrder.getEnergyFee());
                        orderItem.setOrderAmount(orderItem.getChargeAmount());
                    }
                }
            }

            // TODO 订单列表免费订单不显示订单金额，订单详情要显示，后面可能会改
            if(YesOrNo.Yes.name().equals(orderItem.getIsFree())){
                orderItem.setOrderAmount(0);
            }
        });

        OrderNumVO orderNumVO = orderService.getViewModel("get_order_num",OrderNumVO.class,new Object[]{userId,userService.getComId()});
        page.setExtraData(orderNumVO);

        return page;
    }

    /**
     * 查询未完成订单
     *
     * @return
     */
    public List<OrderItemVO> getChargingOrders() {
        List<OrderItemVO> chargingOrders = orderService.getViewModelList("get_charging_orders",OrderItemVO.class,
                new Object[]{userService.get().getComId(),userService.get().getMemberUserId()});

        chargingOrders.stream().forEach(orderItem -> {
            orderItem.setOrderStatus(statusService.getOrderStatus(orderItem.getChargeOrderId(),orderItem.getStatus(),orderItem.getPayStatus(),orderItem.getDeviceType()));

            if(orderItem.getOrderStatus() == OrderEnum.OrderStatus.Doing){
                orderService.setOrderDurationAndAmount(orderItem);
            }

            if(OrderEnum.OrderStatus.Place == orderItem.getOrderStatus() && DeviceTypeEnum.EV.name().equals(orderItem.getDeviceType())){
                EvOrderVO evOrderVO = UMBeanUtils.copyBean(evOrderService.getEntity("charge_order_id",orderItem.getChargeOrderId()),EvOrderVO.class);
                orderService.calcEVOrderPlaceFee(orderItem,evOrderVO);
            }else if(OrderEnum.OrderStatus.Place == orderItem.getOrderStatus() && DeviceTypeEnum.EBox.name().equals(orderItem.getDeviceType())){
                EboxOrderVO eboxOrderVO = UMBeanUtils.copyBean(eboxOrderService.getEntity("charge_order_id",orderItem.getChargeOrderId()),EboxOrderVO.class);
                orderService.calcEBoxOrderPlaceFee(orderItem,eboxOrderVO);
            }

            if(StringUtil.equals(DeviceTypeEnum.EB.name(),orderItem.getDeviceType())){
                EbOrder ebOrder = ebOrderService.getEntity("charge_order_id", orderItem.getChargeOrderId());
                if(ebOrder != null) {
                    if (orderItem.getOrderStatus() == OrderEnum.OrderStatus.Doing && StringUtil.equals(ebOrder.getFeeType(), OrderEnum.FeeType.Energy.name())) {
                        ebOrder.setServiceFee(orderService.getServiceFee(orderItem.getChargeOrderId()));
                        ebOrder.setEnergyFee(orderService.getEnergyFee(orderItem.getChargeOrderId()));

                        orderItem.setChargeAmount(ebOrder.getServiceFee() + ebOrder.getEnergyFee());
                        orderItem.setOrderAmount(orderItem.getChargeAmount());
                    }
                }
            }

            // TODO 订单列表免费订单不显示订单金额，订单详情要显示，后面可能会改
            if(YesOrNo.Yes.name().equals(orderItem.getIsFree())){
                orderItem.setOrderAmount(0);
            }
        });
        return chargingOrders;
    }



    /**
     * 查询微信分账结果
     *
     * @param order
     */
    public void queryWxProfitSharingResult(Order order) {
        ProfitSharingResult result;
        try {
            result = wxManager.getPayService(order.getComId()).getProfitSharingV3Service()
                    .getProfitSharingResult(order.getProfitSharingOutTradeNo(), order.getTransactionId());
        } catch (Exception e) {
            log.error("查询分账结果错误！", e);
            order.setProfitSharingStatus(OrderEnum.ProfitSharingStatus.FAIL.name());
            orderService.saveRow(order);
            return;
        }

        order.setProfitSharingStatus(result.getState());
        orderService.saveRow(order);

        Records sharingRecords = recordsService.getEntity("charge_order_id", order.getChargeOrderId());
        if(null == sharingRecords){
            return;
        }

        ProfitSharingResult.Receiver receiverResult = result.getReceivers().stream().filter(item ->
                item.getAccount().equals(sharingRecords.getAccount())).findFirst().get();
        sharingRecords.setSharingStatus(receiverResult.getResult());
        sharingRecords.setSharingFailReason(receiverResult.getFailReason());
        recordsService.saveRow(sharingRecords);

    }




}
